package jt

import (
	"encoding/binary"
	"fmt"
	"reflect"

	"github.com/dontls/xproto"
)

// onRecvResp 通用应答
func (c *Client) onRecvResp() error {
	sequence := c.jtBytes.toWord()
	msgID := c.jtBytes.toWord()
	code := c.jtBytes.toByte()
	if err := toError(code); err == "" {
		c.SetVal(c.resultKey(sequence), msgID)
	} else {
		c.SetError(c.resultKey(sequence), fmt.Errorf("%s.<%d>", err, code))
	}
	return nil
}

// onRecvQueryTime 通用应答
func (c *Client) onRecvQueryTime() error {
	var res jtBytes
	res.addBCD(nowBytes())
	return c.WriteMessage(0x8004, res.Bytes)
}

// onRevRegister 注册
func (c *Client) onRevRegister() error {
	if c.LinkType == xproto.LinkSignal {
		return nil
	}
	c.terminal = c.jtBytes.toRegister()
	c.DeviceNo = c.phoneNumber()
	c.Session = xproto.UUID()
	var res jtBytes
	res.addWord(c.Msg.SerialNum)
	c.LinkType = xproto.LinkSignal
	err := c.NotifyAccess(c.Msg.Data)
	if err == nil {
		res.addByte(0)
		res.addBytes([]byte(jtprotocolAuthority))
		return c.WriteMessage(0x8100, res.Bytes)
	}
	if err == xproto.ErrObjectExist {
		res.addByte(1) // 重复设备
	} else {
		res.addByte(2) // 无效设备
	}
	c.WriteMessage(0x8100, res.Bytes)
	return err
}

// onRecvAuthority 授权
func (c *Client) onRecvAuthority() error {
	c.jtBytes.toByte()
	return c.WriteAck(0)
}

// onRecvParameters 参数应答
func (c *Client) onRecvParameters() error {
	serial := c.jtBytes.toWord()
	paramNum := c.jtBytes.toByte()
	var i uint8 = 0
	p := jtParameter{}
	for ; i < paramNum; i++ {
		codeID := c.jtBytes.toDWord()
		b := c.jtBytes.Slice(int(c.jtBytes.toByte()))
		item := p.Parse(codeID, &b, nil)
		p.Data = append(p.Data, item)
	}
	c.SetVal(c.resultKey(serial), p)
	return c.WriteAck(0)
}

func (c *Client) OnRecvTerminalProperty() error {
	res := c.jtBytes.toTerminalProperty()
	c.SetVal(c.resultKey(c.key.Property), res)
	return c.WriteAck(0)
}

func (c *Client) OnRecvTerminalUpgrade() error {
	res := c.jtBytes.toTerminalUpgrade()
	c.SetVal(c.resultKey(c.key.Upgrade), res)
	return c.WriteAck(0)
}

// onRecvLoStatus 位置信息
func (c *Client) onRecvLoStatus() error {
	b := c.jtBytes
	st, alrflag := c.doStatusParse(b)
	if alrflag > 0 {
		c.onRecvAlarm(alrflag, &st, b, func(a *xproto.Alarm) {
			c.NotifyAlarm(nil, a)
		})
	} else {
		c.NotifyStatus("jGps", &st)
	}
	return c.WriteAck(0)
}

// onRecvQueryLocation 查询位置
func (c *Client) onRecvQueryLocation() error {
	b := c.jtBytes
	sequence := b.toWord()
	st, _ := c.doStatusParse(b)
	c.SetVal(c.resultKey(sequence), st)
	return c.WriteAck(0)
}

// onRecvAnswer 问题应答
func (c *Client) onRecvAnswer() error {
	sequence := c.jtBytes.toWord()
	AnswerId := c.jtBytes.toByte()
	c.SetVal(c.resultKey(sequence), map[string]interface{}{"answerId": AnswerId})
	return c.WriteAck(0)
}

// 信息点播/取消
func (c *Client) onRecvOnDemand() error {
	b := c.jtBytes
	sequence := b.toWord()
	st, _ := c.doStatusParse(b)
	c.SetVal(c.resultKey(sequence), st)
	return c.WriteAck(0)
}

// onRecvVehiCtrl 车辆控制应答
func (c *Client) onRecvVehiCtrl() error {
	msgType := c.jtBytes.toByte()
	flag := c.jtBytes.toByte()
	c.SetVal(c.resultKey(c.key.OnDemand), map[string]interface{}{"demandType": msgType, "demandFlag": flag})
	return c.WriteAck(0)
}

// onRecvLoStatusBulk 批量上报
func (c *Client) onRecvLoStatusBulk() error {
	b := c.MsgData()
	if b == nil {
		return nil
	}
	num := b.toWord()
	b.toByte() // blindSpot
	for i := uint16(0); i < num; i++ {
		length := b.toWord()
		b := &jtBytes{Bytes: b.toArray(int(length))}
		st, alrflag := c.doStatusParse(b)
		if alrflag > 0 {
			c.onRecvAlarm(alrflag, &st, b, func(a *xproto.Alarm) {
				c.NotifyAlarm(b.Bytes, a)
			})
			continue
		}
		st.Flag = 1
		c.NotifyStatus("jGps", &st)
	}
	return c.WriteAck(0)
}

// onRecvMediaEvent 多媒体事件信息
func (c *Client) onRecvMediaEvent() error {
	b := c.jtBytes
	id := b.toDWord()
	b.toByte()
	b.toByte() // 多媒体格式编码
	// switch  {
	// case 0:
	// 	"JPEG"
	// case 1:
	// 	"TIF"
	// case 2:
	// 	"MP3"
	// case 3:
	// 	"WAV"
	// case "4":
	// 	"WMV"
	// }
	b.toByte()
	b.toByte()
	c.doStatusParse(b)
	// write to file
	var res jtBytes
	res.addDWord(id)
	return c.WriteMessage(0x8800, res.Bytes)
}

// onRecvQueryResult 查询结果
func (c *Client) onRecvQueryResult() error {
	b := c.MsgData()
	if b == nil {
		return nil
	}
	// fmt.Printf("onRecvQueryResult %d MsgTotal %d MsgCur %d data length %d\n", c.MsgSerialNum, c.MsgTotal, c.MsgCur, len(b.Bytes))
	key := c.resultKey(b.toWord())
	res := c.GetValue(key)
	var files []xproto.File
	count := b.toDWord()
	for i := uint32(0); i < count; i++ {
		fl := xproto.File{}
		fl.Channel = int(b.toByte())
		fl.StartTime = dtu(b.toArray(6))
		fl.EndTime = dtu(b.toArray(6))
		// 计算时长
		st, et := toUnixTime(fl.StartTime), toUnixTime(fl.EndTime)
		fl.FileDuration = int(et - st)
		alrType := binary.BigEndian.Uint64(b.toArray(8))
		fptype := b.toByte()
		if fptype == 2 {
			fl.FileType = xproto.FileNormalVideo
			if alrType > 0 {
				fl.FileType = xproto.FileAlarmVideo
			}
		} else if fptype == 1 {
			fl.FileType = xproto.FileNormalVoice
			if alrType > 0 {
				fl.FileType = xproto.FileAlarmVoice
			}
		}
		stream := b.toByte() // 码流类型
		store := b.toByte()
		fl.FileSize = int(b.toDWord())
		fl.FileName = virtualRecFile(fl.Channel, st, et, alrType, fptype, stream, store)
		if res == nil {
			c.NotifyFile(&fl)
			continue
		}
		files = append(files, fl)
	}
	// 持续接收数据
	if res != nil {
		if v, ok := reflect.ValueOf(res.Data).Interface().(*[]xproto.File); ok {
			*v = append(*v, files...)
			res.Done <- struct{}{}
		} else {
			c.SetVal(key, files)
		}
	} else {
		c.NotifyFile(&xproto.File{}) // 文件搜索结束
	}
	return c.WriteAck(0)
}

// onRecvFtpResp 可以由内部触发
func (c *Client) onRecvFtpResp() error {
	sequence := c.jtBytes.toWord()
	result := c.jtBytes.toByte()
	c.SetVal(c.resultKey(sequence), map[string]interface{}{"result": result})
	return nil
}

func (c *Client) onRecvAVProperty() error {
	r := jt0x1003{}
	r.Audio.Encoder = c.jtBytes.toByte()
	r.Audio.Chls = c.jtBytes.toByte()
	r.Audio.SampleRate = c.jtBytes.toByte()
	r.Audio.SampleBit = c.jtBytes.toByte()
	r.Audio.FrameLength = c.jtBytes.toWord()
	r.Video.Enable = c.jtBytes.toByte()
	r.Video.Encoder = c.jtBytes.toByte()
	r.Audio.MaxChls = c.jtBytes.toByte()
	r.Video.MaxChls = c.jtBytes.toByte()
	c.SetVal(c.resultKey(c.key.AVProperty), r)
	return nil
}

func (c *Client) onRecvPassengerTraffic() error {
	r := jt0x1005{}
	r.StartTime = dtu(c.jtBytes.toArray(6))
	r.EndTime = dtu(c.jtBytes.toArray(6))
	r.Up = c.jtBytes.toWord()
	r.Down = c.jtBytes.toWord()
	return nil
}
